package com.i360day.invoker.security;

import com.i360day.invoker.security.annotation.IgnoreRemoteService;
import com.i360day.invoker.support.RemoteExporter;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @program: spring-cloud-invoker-parent
 * @description: HTTPInvoker config
 * @author: liju.z
 * @create: 2021-03-16 09:53
 **/
@Configuration(proxyBeanMethods = false)
public class HttpInvokerSecurityConfiguration {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public SecurityFilterChain invokerSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
        //找到暴露的service，对应的beanNameUrlHandlerMapping
        Set<String> ignoreUrlSet = new HashSet<>();
        //AbstractHandlerMapping
        Map<String, BeanNameUrlHandlerMapping> beansOfType = applicationContext.getBeansOfType(BeanNameUrlHandlerMapping.class);
        beansOfType.values().forEach(beanNameUrlHandlerMapping -> {
            beanNameUrlHandlerMapping.getHandlerMap().forEach((url, classBean) -> {
                if (classBean instanceof RemoteExporter) {
                    RemoteExporter remoteExporter = (RemoteExporter) classBean;
                    IgnoreRemoteService annotation = AnnotationUtils.findAnnotation(AopProxyUtils.ultimateTargetClass(remoteExporter.getService()), IgnoreRemoteService.class);
                    if (annotation != null) {
                        ignoreUrlSet.add(url);
                    }
                }
            });
        });
        if (ignoreUrlSet.isEmpty()) {
            return httpSecurity.csrf().disable().build();
        } else {
            //不验证地址,放行....
            return httpSecurity.csrf().disable().authorizeHttpRequests().requestMatchers(ignoreUrlSet.stream().toArray(String[]::new)).permitAll().and().build();
        }
    }
}
